import json
import datetime

from django.shortcuts import render, render_to_response, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.views.generic.base import View
from django.contrib.auth.hashers import make_password
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.urls import reverse_lazy
from django.views.decorators.csrf import csrf_exempt


from users.models import UserProfile, EmailVerifyRecord
from users.forms import LoginForm, RegisterForm, ForgetForm, EditForm, UploadImageForm
from common.email import send_register_email


# Create your views here.
# 404/403等处理
# def page_not_found(request):
#     return render_to_response('404.html')
#
#
# def page_error(request):
#     return render_to_response('403.html')


# def permission_denied(reqeust):
    # return render_to_response('')


# 返回到主页
@login_required
def index(request):
    # username = request.users.username
    return render(request, 'base.html')


# 自定义的一个用户验证过程，主要是返回该用户
class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = UserProfile.objects.get(Q(email=username) | Q(username=username))
            if user.check_password(password):
                return user
        except Exception as e:
            print(e)
            return None


# 激活用户的类
class ActiveUserView(View):
    @staticmethod
    def get(request, active_code):
        all_records = EmailVerifyRecord.objects.filter(code=active_code)
        if all_records:
            for record in all_records:
                email = record.email
                user = UserProfile.objects.get(email=email)
                user.is_active = True
                user.save()
        else:
            pass
        return render(request, "users/login.html")


# 用户登录的类
class LoginView(View):
    # 返回页面
    @staticmethod
    def get(request):
        return render(request, 'users/login.html')

    # 处理登录表单
    @staticmethod
    def post(request):
        """处理用户的表单数据，处理流程:1.实例化表单，表单的判定
        2.用户信息的验证，利用username，从数据库中读取用户信息
        3.判断是否激活
        :param request:
        :return:
        """
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            username = request.POST.get("username", "")
            password = request.POST.get("password", "")
            user = CustomBackend().authenticate(request, username=username, password=password)
            if user is not None:
                if user.is_active:
                    # login函数实际就已经将user与request进行关联了
                    login(request, user)
                    # 重点重点，如果利用view进行重定向，会在ajax回调中报错，因为传递的是一个html而不是json
                    # 这是就需要回传一个json，利用ajax回调函数进行判断，然后利用ajax进行所谓的重定向
                    response = dict()
                    response["status"] = 1
                    json_response = JsonResponse(response)  # 设置cookie来进行确认用户登录
                    json_response.set_cookie("username", username)
                    return json_response
                else:
                    response = dict()
                    response["error"] = "用户尚未激活"
                    response["status"] = -1
                    return JsonResponse(response)
            else:
                response = dict()
                response["status"] = -1
                response["error"] = "用户名或密码错误"
                return JsonResponse(response)
        else:
            # 表单的错误信息是以html的形式进行保存，存为字典形式
            error_msg = login_form.errors   # errors为错误信息
            response = dict()
            response["status"] = -2  # 这里使用-2是用来区分表单错误与账户密码错误
            response["error"] = error_msg
            return JsonResponse(response)


# 用户注册的类
class RegisterView(View):
    @staticmethod
    def post(request):
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            username = request.POST.get("username", "")
            email = request.POST.get("email", "")
            # mobile = request.POST.get("mobile", "")
            response = dict()
            # 判断注册的用户是否已经存在
            if UserProfile.objects.filter(Q(email=email) | Q(username=username)):
                response["status"] = -1
                response["error"] = "用户已经存在了"
                return JsonResponse(response)
            pass_word = request.POST.get("password1", "")
            user_profile = UserProfile()
            user_profile.username = username
            # user_profile.mobile = mobile
            user_profile.email = email
            user_profile.is_active = False
            # 进行密码的hash编码过程
            user_profile.password = make_password(pass_word)
            user_profile.save()
            # 发送验证邮件
            send_register_email(email, 'register')
            response = dict()
            response["status"] = 1
            return JsonResponse(response)
        else:
            error_msg = register_form.errors  # 用户注册的表单错误
            response = dict()
            response["status"] = -2
            response["error"] = error_msg
            return JsonResponse(response)


class LogoutView(View):
    @staticmethod
    def get(request):
        logout(request)
        response = HttpResponseRedirect(reverse("user_login"))
        response.delete_cookie("username")
        return response


# 用户个人信息（包括修改密码）的类
class EditUserInfo(View):
    @login_required
    @staticmethod
    def post(request):
        """这里表单的数据有很多
        :param request:
        :return:
        """
        # users = UserProfile.objects.all()
        # username = request.COOKIES["username"]
        # user = UserProfile.objects.get(Q(email=username) | Q(username=username))
        edit_form = EditForm(request.POST)
        if edit_form.is_valid():
            # 先不进行错误处理
            username = request.COOKIES["username"]
            user = UserProfile.objects.get(Q(email=username) | Q(username=username))
            for key in edit_form.data.keys():
                if edit_form.data[key]:  # 数据不为空即可
                    # 判断key是否为password进行密码的修改
                    if key == "password":
                        pass
                        # self.reset_password(user, edit_form)
                    elif key in ["rept_new_pass", "new_pass"]:
                        pass
                    else:
                        user.__dict__[key] = edit_form.data[key]
            username = request.COOKIES["username"]  # 取出cookies的值
            user = UserProfile.objects.get(username=username)  # 取出相应的用户
            password = request.POST.get("password", "")
            if user.password != make_password(password):  # 旧密码相等
                response = dict()
                response["status"] = -1
                response["error"] = "密码输入有误"
                return JsonResponse(response)
            password1 = request.POST.get("password1", "")
            password2 = request.POST.get("password2", "")
            if password1 != password2:
                response = dict()
                response["status"] = -1
                response["error"] = "确认密码与新密码不一致"
                return JsonResponse(response)
            # 更新用户密码
            user.password = make_password(password1)
            response = dict()
            response["status"] = 1
            return JsonResponse(response)
        else:  # 表单的错误
            response = dict()
            response["status"] = -2
            response["error"] = edit_form.errors
            return JsonResponse(response)

    # 密码的重置
    @staticmethod
    def reset_password(user, edit_form):
        """判断一下用户的原密码是否正确，新密码是否能用
        :param user:
        :param edit_form:
        :return:
        """
        old_pass = edit_form.data.get("old_pass", "")  # 旧密码
        new_pass = edit_form.data.get("new_pass", "")  # 新密码
        rept_new_pass = edit_form.data.get("rept_new_pass", "")  # 确认密码
        # 这一段的判断应该可以在前端进行编写
        if old_pass and new_pass and rept_new_pass:
            # 1.判断原密是否正确
            if make_password(old_pass) == user.password:
                user.password = new_pass  # 更新用户密码
            else:
                return -2  # 原密码填写不对
        else:
            return -1  # 密码框必须要填满


# 用户忘记密码的类
class ForgetView(View):
    @staticmethod
    @login_required
    def post(request):
        """用户通过邮箱验证进行密码的修改，可以在以后加一个用户名的填写
        :param request:
        :return:
        """
        forget_form = ForgetForm(request.POST)
        if forget_form.is_valid():
            email = request.POST.get("email", "")
            user = UserProfile.objects.get(Q(email=email))
            if not user:
                response = dict()
                response["status"] = -1
                response["error"] = "用户不存在"
                return JsonResponse(response)
            # password = request.POST.get("password", "")
            # user_profile.update(is_active=False, password=make_password(password))  # 将用户的激活状态编程False
            # 发送验证邮件
            send_register_email(email, 'forget')
            # 进行重定向

            response_json = dict()
            response_json["status"] = 1
            response = JsonResponse(response_json)
            response.delete_cookie("username")  # 这里要和退出用户登录一样删除用户的cookie
            return JsonResponse(response_json)
        else:
            form_error = forget_form.errors  # 忘记密码的表单错误
            response = dict()
            response["status"] = -2
            response["error"] = form_error
            return JsonResponse(response)


# 用户个人中心的视图类
class ProfileView(View):
    @staticmethod
    @login_required
    def get(request):
        return render(request, 'users/profile.html')


# 获取用户信息的json文件
@login_required
def get_profile_json(request):
    if request.method == "GET":
        username = request.COOKIES.get("username")  # 获取用户名
        user = UserProfile.objects.get(Q(email=username) | Q(username=username))
        response = dict()
        # 这里需要明白有些属性不存在，这里如果要修改数据库就比较麻烦了
        keys = ["username", "email", "date_joined", "birthday", "address", "mobile", "image"]
        time_format = "%Y-%m-%d %H:%M:%S"
        for key in keys:
            value = user.__dict__[key]
            if value:
                if key == "date_joined":
                    value = value.strftime(time_format)  # 将日期变成str
                elif key == "birthday":
                    value = datetime.datetime.now().year - value.year
                    value = value if value > 0 else 0
                response[key] = value

        return JsonResponse(response)



from test.works import job2, job1

from rq import Queue, Worker
from rq.job import Job
from redis import Redis
import time

def ceshi(request):
    q = Queue(connection=Redis())
    print(time.ctime())
    res1 = q.enqueue(job1)
    res2 = q.enqueue(job2)
    job_id = res1.get_id()
    print(time.ctime())
    print(job_id)

    return HttpResponse("1")